package com.poetry.vup.common.util.jwt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JwtToken生成的工具类
 * JWT token的格式：header.payload.signature
 * header的格式（算法、token的类型）：
 * {"alg": "HS512","typ": "JWT"}
 * payload的格式（用户名、用户类型、sessionid、创建时间）：
 * {"sub":"wan", "jti":"321425125", "created":1489079981393,"exp":1489684781}
 * 采用RSA非对称加解密，只有这里能访问到私钥
 */
@Component
@Slf4j
public class JwtTokenGenerator {
    private static final String CLAIM_KEY_USERNAME = "sub";
    private static final String CLAIM_KEY_UID = "password";
    private static final String CLAIM_KEY_SESSIONID = "ses";
    private static final String CLAIM_KEY_CREATED = "created";
    @Value("${jwt.secret}")
    private String secret;
//    @Value("${jwt.expiration}")
//    private static final Long expiration = 3600 * 2l;
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    /**
     * 根据负责生成JWT的token
     */
    private String generateToken(Map<String, Object> claims) {
    	PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(secret));
        KeyFactory keyf;
        PrivateKey priKey = null;
		try {
			keyf = KeyFactory.getInstance("RSA");
			priKey = keyf.generatePrivate(priPKCS8);
		} catch (NoSuchAlgorithmException e) {
			log.error("JWT生成私钥错误。", e);
		} catch (InvalidKeySpecException e) {
			log.error("JWT私钥无效。", e);
		}
        return Jwts.builder()
                .setClaims(claims)
                //.setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 *60 *1000))//一天有效时间
                .signWith(SignatureAlgorithm.RS256, priKey)
                .compact();
    }

    /**
     * 生成token的过期时间
     */
//    private Date generateExpirationDate() {
//        return new Date(System.currentTimeMillis() + expiration * 1000);
//    }

    public String generateToken(String username, String password, String sessionid) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(CLAIM_KEY_USERNAME, username);
        claims.put(CLAIM_KEY_UID, password);
        claims.put(CLAIM_KEY_SESSIONID, sessionid);
        claims.put(CLAIM_KEY_CREATED, new Date());
        return generateToken(claims);
    }

    /**
     * 刷新token
     */
    public String refreshToken(String token) {
        Claims claims = jwtTokenUtil.getClaimsFromToken(token);
        claims.put(CLAIM_KEY_CREATED, new Date());
        return generateToken(claims);
    }
}
